﻿using System;
using System.Collections;
using System.Collections.Generic;

namespace SlamCms.Collections
{
	public class CollectionWithKey<TKey, TValue> : ICollection<TValue>, ICollection where TValue : class
	{
		private readonly Dictionary<TKey, TValue> _dictionary;
		private readonly Func<TValue, TKey> _keySelector;

		public CollectionWithKey(Func<TValue, TKey> keySelector, IEnumerable<TValue> values = null)
		{
			_dictionary = new Dictionary<TKey, TValue>();
			this._keySelector = keySelector;
			if (values != null)
			{
				foreach (var elem in values)
					this.Add(elem);
			}
		}

		public void Add(TValue item)
		{
			_dictionary.Add(_keySelector(item), item);
		}

		public TValue Find(TKey key)
		{
			TValue value;
			if (_dictionary.TryGetValue(key, out value))
				return value;
			return null;
		}

		public TValue this[TKey index]
		{
			get
			{
				TValue result;
				if (!_dictionary.TryGetValue(index, out result))
					return null;
				return result;
			}
		}

		public IEnumerable<TValue> Find(params TKey[] keys)
		{
			foreach (var key in keys)
			{
				var value = Find(key);
				if (value != null)
					yield return value;
			}
		}

		public bool Contains(TValue item)
		{
			return _dictionary.ContainsValue(item);
		}

		public void CopyTo(TValue[] array, int arrayIndex)
		{
			_dictionary.Values.CopyTo(array, arrayIndex);
		}

		public bool IsReadOnly
		{
			get { return false; }
		}

		public bool Remove(TValue item)
		{
			return _dictionary.Remove(_keySelector(item));
		}

		public IEnumerator<TValue> GetEnumerator()
		{
			return _dictionary.Values.GetEnumerator();
		}

		public void Clear()
		{
			_dictionary.Clear();
		}

		public int Count
		{
			get { return _dictionary.Count; }
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return _dictionary.Values.GetEnumerator();
		}

		public void CopyTo(Array array, int index)
		{
			throw new NotImplementedException();
		}

		public bool IsSynchronized
		{
			get { throw new NotImplementedException(); }
		}

		public object SyncRoot
		{
			get { throw new NotImplementedException(); }
		}
	}
}
